package cn.schoolwow.workflow.module.task.action.flow.complete.nodeType.gateway;

import cn.schoolwow.quickdao.domain.transaction.Transaction;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.instanceList.QueryInstanceList;
import cn.schoolwow.workflow.domain.deploy.DeployGatewayPositionType;
import cn.schoolwow.workflow.domain.task.TaskType;
import cn.schoolwow.workflow.entity.WorkFlowInstance;
import cn.schoolwow.workflow.entity.WorkFlowNode;
import cn.schoolwow.workflow.entity.WorkFlowNodeJump;
import cn.schoolwow.workflow.module.common.flow.AddWorkFlowHistoryFlow;
import cn.schoolwow.workflow.module.task.action.domain.CompleteTaskOption;
import cn.schoolwow.workflow.module.task.action.flow.complete.nodeType.gateway.common.SetCurrentGatewayNodeCommonFlow;
import cn.schoolwow.workflow.module.task.action.flow.complete.nodeType.gateway.common.SetMatchSuccessorJumpNodeListCommonFlow;
import cn.schoolwow.workflow.module.task.action.flow.complete.nodeType.gateway.common.SetSuccessorJumpNodeListCommonFlow;
import cn.schoolwow.workflow.module.task.action.flow.complete.transaction.InsertWorkFlowTaskFlow;

import java.util.List;

public class HandleExclusiveGatewayFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        flowContext.executeFlowList(new SetCurrentGatewayNodeCommonFlow());
        checkExclusiveGatewayStart(flowContext);
        checkExclusiveGatewayEnd(flowContext);
    }

    @Override
    public String name() {
        return "处理排他网关流程";
    }

    private void checkExclusiveGatewayStart(FlowContext flowContext){
        WorkFlowNode gatewayNode = flowContext.checkData("gatewayNode", WorkFlowNode.class);
        DeployGatewayPositionType deployGatewayPositionType = flowContext.checkInstanceData(DeployGatewayPositionType.class);

        if(!DeployGatewayPositionType.Start.equals(deployGatewayPositionType)){
            return;
        }

        WorkFlowInstance workFlowInstance = flowContext.checkInstanceData(WorkFlowInstance.class);
        CompleteTaskOption completeTaskOption = flowContext.checkInstanceData(CompleteTaskOption.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);

        WorkFlowNodeJump exclusiveGatewayNodeJump = getExclusiveGatewayJump(flowContext);
        WorkFlowNode exclusiveGatewayNextNode = transaction.query(WorkFlowNode.class)
                .addQuery("id", exclusiveGatewayNodeJump.getNextNodeId())
                .execute()
                .getOne();

        flowContext.startFlow(new AddWorkFlowHistoryFlow())
                .putCurrentCompositeFlowData("message", "选择分支["+exclusiveGatewayNodeJump.getJumpName()+"]")
                .execute();

        flowContext.putTemporaryData("nextNode", exclusiveGatewayNextNode);

        flowContext.startFlow(new InsertWorkFlowTaskFlow())
                .putCurrentCompositeFlowInstanceData(TaskType.COMPLETE)
                .execute();

        completeTaskOption.shouldUpdateInstanceCurrentNodeId = true;
        workFlowInstance.setWorkFlowNodeId(gatewayNode.getId());
    }

    private void checkExclusiveGatewayEnd(FlowContext flowContext){
        DeployGatewayPositionType deployGatewayPositionType = flowContext.checkInstanceData(DeployGatewayPositionType.class);

        if(!DeployGatewayPositionType.End.equals(deployGatewayPositionType)){
            return;
        }

        WorkFlowNode gatewayNode = flowContext.checkData("gatewayNode", WorkFlowNode.class);
        WorkFlowInstance workFlowInstance = flowContext.checkInstanceData(WorkFlowInstance.class);
        CompleteTaskOption completeTaskOption = flowContext.checkInstanceData(CompleteTaskOption.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);

        flowContext.executeFlowList(new SetSuccessorJumpNodeListCommonFlow());
        List<WorkFlowNodeJump> successorJumpNodeList = flowContext.checkData("successorJumpNodeList", List.class);

        WorkFlowNode exclusiveGatewayNextNode = transaction.query(WorkFlowNode.class)
                .addQuery("id", successorJumpNodeList.get(0).getNextNodeId())
                .execute()
                .getOne();

        flowContext.startFlow(new InsertWorkFlowTaskFlow())
                .putCurrentCompositeFlowData("nextNode", exclusiveGatewayNextNode)
                .putCurrentCompositeFlowInstanceData(TaskType.COMPLETE)
                .execute();

        completeTaskOption.shouldUpdateInstanceCurrentNodeId = true;
        workFlowInstance.setWorkFlowNodeId(gatewayNode.getId());
    }

    private WorkFlowNodeJump getExclusiveGatewayJump(FlowContext flowContext){
        flowContext.executeFlowList(new SetMatchSuccessorJumpNodeListCommonFlow());

        List<WorkFlowNodeJump> matchWorkFlowNodeJumpList = flowContext.getData("matchWorkFlowNodeJumpList", List.class);

        if(matchWorkFlowNodeJumpList.size()==1){
            return matchWorkFlowNodeJumpList.get(0);
        }

        //根据优先级
        List<WorkFlowNodeJump> orderWorkFlowNodeJumpList = QueryInstanceList.newQuery(matchWorkFlowNodeJumpList)
                .orderByAsc("priorityLevel")
                .execute()
                .getList();
        return orderWorkFlowNodeJumpList.get(0);
    }
}
